package com.lanzuo.yxd.scanner.manager;

import com.lanzuo.yxd.scanner.config.LaneConfig;
import com.lanzuo.yxd.scanner.config.LaneConfigList;
import com.lanzuo.yxd.scanner.conveyor.SensorSignalListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ConveyorTaskManager {
    private final ExecutorService executor;
    private final Map<String, Thread> activeThreads = new ConcurrentHashMap<>();
    private final ScheduledExecutorService monitorScheduler;

    @Resource
    LaneConfigList laneConfigList;

    public ConveyorTaskManager(LaneConfigList laneConfigList) {
        this.laneConfigList = laneConfigList;
        // 使用自定义线程工厂，便于命名和识别
        this.executor = Executors.newCachedThreadPool(r -> {
            Thread t = new Thread(r);
            // 非守护线程，防止 JVM 退出
            t.setDaemon(false);
            return t;
        });

        this.monitorScheduler = Executors.newScheduledThreadPool(1);
    }

    @EventListener(ApplicationReadyEvent.class)
    public void start() {
        log.info("开始启动所有轨道传感器监听任务...");
        reloadAllListeners();

//        // 每 10 秒检查一次线程是否存活，自动重启
//        monitorScheduler.scheduleAtFixedRate(this::monitorAndRestart, 10, 10, TimeUnit.SECONDS);
    }

    /**
     * 根据轨道配置加载listener
     */
    private void reloadAllListeners() {
        List<LaneConfig> configs = laneConfigList.getConfigs();

        if (configs == null || configs.isEmpty()) {
            log.warn("没有配置任何轨道！");
            return;
        }

        if (configs.size() > 2) {
            log.error("轨道数量超过2，只会运行前两个配置");

            // 筛选前两个
            configs = configs.stream().limit(2).collect(Collectors.toList());
        }

        for (LaneConfig config : configs) {
            if (!config.getEnable()) {
                continue;
            }
            String key = "lane-" + config.getLaneNo();
            if (!activeThreads.containsKey(key)) {
                startListenerForLane(config, key);
            }
        }
    }

    private void startListenerForLane(LaneConfig config, String key) {
        SensorSignalListener listener = new SensorSignalListener(config);
        Thread thread = new Thread(listener, "Sensor-Lane-" + config.getLaneNo());

        thread.setUncaughtExceptionHandler((t, e) -> {
            log.error("传感器线程 [{}] 发生未捕获异常", t.getName(), e);
        });

        thread.start();
        activeThreads.put(key, thread);

        log.info("已启动轨道 {} 的传感器监听线程", config.getLaneNo());
    }

    /**
     * 检查线程是否因特殊情况被打断，以及打断后的重启操作
     */
    private void monitorAndRestart() {
        List<LaneConfig> configs = laneConfigList.getConfigs();
        if (configs == null) return;

        for (LaneConfig config : configs) {
            String key = "lane-" + config.getLaneNo();
            Thread thread = activeThreads.get(key);

            if (thread == null || !thread.isAlive()) {
                log.warn("检测到轨道 {} 的监听线程已退出，正在重启...", config.getLaneNo());
                activeThreads.remove(key); // 清理旧引用
                startListenerForLane(config, key);
            }
        }
    }

    @PreDestroy
    public void shutdown() {
        log.info("正在关闭所有传感器监听线程...");
        activeThreads.values().forEach(thread -> {
            if (thread.isAlive()) {
                thread.interrupt();
            }
        });
        executor.shutdown();
        monitorScheduler.shutdown();
        try {
            if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
            if (!monitorScheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                monitorScheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        log.info("传感器监听线程已全部关闭");
    }
}
